/* 

原生具备 Iterator 接口的数据结构如下:

Array
Map
Set
String
TypedArray
函数的 arguments 对象
NodeList 对象

遍历器对象除了具有next()方法，还可以具有return()方法和throw()方法。
如果你自己写遍历器对象生成函数，那么next()方法是必须部署的，return()方法和throw()方法是否部署是可选的

*/

// 法1
var it = makeIterator(["a", "b"]);

it.next(); // { value: "a", done: false }
it.next(); // { value: "b", done: false }
it.next(); // { value: undefined, done: true }

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function () {
      return nextIndex < array.length
        ? { value: array[nextIndex++], done: false }
        : { value: undefined, done: true };
    },
  };
}

// 法2
// 为对象添加 Iterator 接口
const obj = {
  data: ["hello", "world"],
  [Symbol.iterator]() {
    const self = this;
    let index = 0;
    return {
      next() {
        if (index < self.data.length) {
          return {
            value: self.data[index++],
            done: false,
          };
        }
        return { value: undefined, done: true };
      },
    };
  },
};

// 法3
// Symbol.iterator()方法的最简单实现，还是使用 Generator 函数
const myIterable = {
  [Symbol.iterator]: function* () {
    yield 1;
    yield 2;
    yield 3;
  },
};
[...myIterable]; // [1, 2, 3]

// 或者采用下面的简洁写法

const obj = {
  *[Symbol.iterator]() {
    yield "hello";
    yield "world";
  },
};

for (const x of obj) {
  console.log(x);
}
// "hello"
// "world"
